package com.alexfu.countdownview;


import ohos.agp.components.AttrHelper;
import ohos.agp.components.AttrSet;
import ohos.agp.components.Component;
import ohos.agp.render.Canvas;
import ohos.agp.render.Paint;
import ohos.agp.utils.Color;
import ohos.app.Context;
import ohos.eventhandler.EventRunner;

import java.util.Locale;

/**
 * CountDownView
 *
 * @since 2021-07-02
 */
public class CountDownView extends Component implements Component.DrawTask {
    private static final int NUM_15 = 15;
    private static final int NUM_2 = 2;
    private static final float NUM_3 = 2.9f;
    private static final float NUM_22 = 2.2f;
    private static final float NUM_21 = 2.2f;
    private static final float NUM_16 = 1.71f;
    private static final float NUM_17 = 1.68f;
    private static final float NUM_14 = 1.37f;
    private static final int NUM_30 = 30;
    private static final int HOUR = 3600000;
    private static final int MIN = 60000;
    private static final int SEC = 1000;
    private float metrics = AttrHelper.getDensity(getContext());
    private Paint textPaint = new Paint();
    private Paint otherPaint = new Paint();
    private String text;
    private WeakHandler weakHandler;
    private long startDuration;
    private long currentDuration;
    private boolean timerRunning;
    private int textSize;
    private CountDownListener listener;
    private Runnable runnable = new Runnable() {
        @Override
        public void run() {
            currentDuration = currentDuration - SEC;
            updateText(currentDuration);
            postLayout();
            if (currentDuration == 0) {
                listener.onFinishCountDown();
                weakHandler.removeCallbacks(this::run);
                timerRunning = false;
                return;
            }
            weakHandler.postDelayed(runnable, SEC);
            postLayout();
        }
    };

    /**
     * CountDownView
     *
     * @param context context
     * @param attrs   attrs
     */
    public CountDownView(Context context, AttrSet attrs) {
        super(context, attrs);
        init(attrs);
    }

    private void init(AttrSet attrs) {
        addDrawTask(this::onDraw);
        textPaint.setColor(new Color(Color.getIntColor("#737373")));
        otherPaint.setColor(new Color(Color.getIntColor("#737373")));
        startDuration = TypedAttrUtils.getInteger(attrs, "startDuration", 0);
        textSize = TypedAttrUtils.getDimensionPixelSize(attrs, "textSize", (int) vpToPx(NUM_30));
        otherPaint.setTextAlign(textSize);
        otherPaint.setTextSize((int) vpToPx(NUM_15));
        textPaint.setTextSize(textSize);
        textPaint.setAntiAlias(true);
        setStartDuration(startDuration);
    }

    /**
     * setStartDuration
     *
     * @param duration duration
     */
    public void setStartDuration(long duration) {
        if (timerRunning) {
            return;
        }
        startDuration = duration;
        currentDuration = duration;
        updateText(duration);
    }

    /**
     * start
     */
    public void start() {
        if (timerRunning) {
            return;
        }
        if (currentDuration == 0) {
            listener.onFinishCountDown();
            return;
        }
        timerRunning = true;
        EventRunner runner = EventRunner.getMainEventRunner();
        weakHandler = new WeakHandler(runner);
        weakHandler.postDelayed(runnable, SEC);
    }

    /**
     * reset
     */
    public void reset() {
        stop();
        setStartDuration(startDuration);
        postLayout();
    }

    /**
     * stop
     */
    public void stop() {
        if (!timerRunning) {
            return;
        }
        timerRunning = false;
        weakHandler.removeCallbacks(runnable);
    }

    /**
     * setListener
     *
     * @param downListener downListener
     */
    public void setListener(CountDownListener downListener) {
        this.listener = downListener;
    }

    /**
     * updateText
     *
     * @param duration duration
     */
    public void updateText(long duration) {
        text = generateCountdownText(duration);
        invalidate();
    }


    static String generateCountdownText(long duration) {
        long hr = (int) (duration / HOUR);
        long min = (int) ((duration - (hr * HOUR)) / MIN);
        long sec = (int) ((duration - (hr * HOUR) - (min * MIN)) / SEC);

        Locale locale = Locale.getDefault();
        String format = "%02d";
        String formattedHr = String.format(locale, format, hr);
        String formattedMin = String.format(locale, format, min);
        String formattedSec = String.format(locale, format, sec);

        return String.format(locale, "%sh %sm %ss", formattedHr, formattedMin, formattedSec);
    }


    private float vpToPx(int dp) {
        return AttrHelper.vp2px(dp, metrics);
    }

    /**
     * onDraw
     *
     * @param component component
     * @param canvas    canvas
     */
    @Override
    public void onDraw(Component component, Canvas canvas) {
        int height = getHeight() / NUM_2;
        int width = getWidth();
        String[] hs = text.split("h");
        String[] ms = hs[1].split("m");
        String[] so = ms[1].split("s");
        canvas.drawText(textPaint, hs[0], width / NUM_3, height);

        canvas.drawText(otherPaint, "h", width / NUM_21, height);

        canvas.drawText(textPaint, ms[0], width / NUM_22, height);

        canvas.drawText(otherPaint, "m", width / NUM_16, height);

        canvas.drawText(textPaint, so[0], width / NUM_17, height);

        canvas.drawText(otherPaint, "s", width / NUM_14, height);
    }
}
